using System.Collections.Generic;
using System.Linq;

namespace ICP_MS.Plugin.HPLC;

internal class InterferenceCorrection
{
	public static List<double> dataEnhance(double[] data, int para)
	{
		List<double> enhancedData = new List<double>();
		List<Complex> fftResult = new List<Complex>();
		fftResult = FreqAnalyzer.FFT(data, invert: true).ToList();
		for (int j = 0; j < data.Count(); j++)
		{
			fftResult[j].Real = fftResult[j].Real / (double)data.Count();
			fftResult[j].Image = fftResult[j].Image / (double)data.Count();
		}
		List<Complex> tempList = new List<Complex>();
		List<Complex> fftExpand = new List<Complex>();
		List<Complex> enhancement = new List<Complex>();
		tempList = fftResult.Take(data.Count() / 2).ToList();
		fftResult.RemoveRange(0, data.Count() / 2);
		fftResult.AddRange(tempList);
		Complex[] temp = new Complex[(para - 1) * data.Count() / 2];
		for (int i = 0; i < (para - 1) * data.Count() / 2; i++)
		{
			temp[i] = new Complex();
		}
		fftExpand.AddRange(temp.ToList());
		fftExpand.AddRange(fftResult);
		fftExpand.AddRange(temp.ToList());
		enhancement = FreqAnalyzer.FFT(fftExpand.ToArray(), invert: false).ToList();
		return FreqAnalyzer.Cmp2Mdl(enhancement.ToArray()).ToList();
	}

	public static List<double> interpolation(double[] data, InterpolatipnType interpolatipnType)
	{
		List<double> interpolationCurve = new List<double>();
		switch (interpolatipnType)
		{
		case InterpolatipnType.MiddleValue:
		{
			for (int k = 0; k < 2 * data.Length - 1; k++)
			{
				if (k % 2 == 0)
				{
					interpolationCurve.Add(data[k / 2]);
				}
				else
				{
					interpolationCurve.Add((data[(k - 1) / 2] + data[(k + 1) / 2]) / 2.0);
				}
			}
			break;
		}
		case InterpolatipnType.Enhancement:
		{
			List<Complex> fftResult = new List<Complex>();
			fftResult = FreqAnalyzer.FFT(data, invert: true).ToList();
			for (int j = 0; j < data.Count(); j++)
			{
				fftResult[j].Real = fftResult[j].Real / (double)data.Count();
				fftResult[j].Image = fftResult[j].Image / (double)data.Count();
			}
			List<Complex> tempList = new List<Complex>();
			List<Complex> fftExpand = new List<Complex>();
			List<Complex> enhancement = new List<Complex>();
			tempList = fftResult.Take(data.Count() / 2).ToList();
			fftResult.RemoveRange(0, data.Count() / 2);
			fftResult.AddRange(tempList);
			Complex[] temp = new Complex[data.Count() / 2];
			for (int i = 0; i < data.Count() / 2; i++)
			{
				temp[i] = new Complex();
			}
			fftExpand.AddRange(temp.ToList());
			fftExpand.AddRange(fftResult);
			fftExpand.AddRange(temp.ToList());
			enhancement = FreqAnalyzer.FFT(fftExpand.ToArray(), invert: false).ToList();
			interpolationCurve = FreqAnalyzer.Cmp2Mdl(enhancement.ToArray()).ToList();
			break;
		}
		}
		return interpolationCurve;
	}

	public static List<double> smooth(double[] data, SmoothType smoothType, int smoothTimes)
	{
		List<double> smoothCurve = new List<double>();
		double[] dataCopy = new double[data.Length];
		for (int n = 1; n < dataCopy.Length; n++)
		{
			dataCopy[n] = data[n];
		}
		switch (smoothType)
		{
		case SmoothType.PointsAverage:
		{
			for (int k3 = 0; k3 < smoothTimes; k3++)
			{
				if (k3 % 2 == 0)
				{
					for (int l = 0; l < data.Length - 1; l++)
					{
						data[l] = (data[l] + data[l + 1]) / 2.0;
					}
					continue;
				}
				for (int m = data.Length - 1; m > 0; m--)
				{
					data[m] = (data[m] + data[m - 1]) / 2.0;
				}
			}
			break;
		}
		case SmoothType.FivePointsSmooth:
		{
			for (int k2 = 0; k2 < smoothTimes; k2++)
			{
				for (int k = 2; k < data.Length - 3; k++)
				{
					data[k] = (-3.0 * data[k - 2] + 12.0 * data[k - 1] + 17.0 * data[k] + 12.0 * data[k + 1] - 3.0 * data[k + 2]) / 35.0;
				}
			}
			break;
		}
		case SmoothType.TestFFT:
		{
			List<Complex> fftResult = new List<Complex>();
			fftResult = FreqAnalyzer.FFT(data, invert: true).ToList();
			for (int j = 0; j < data.Count(); j++)
			{
				fftResult[j].Real = fftResult[j].Real / (double)data.Count();
				fftResult[j].Image = fftResult[j].Image / (double)data.Count();
			}
			List<Complex> tempList = new List<Complex>();
			List<Complex> fftExpand = new List<Complex>();
			List<Complex> enhancement = new List<Complex>();
			tempList = fftResult.Take(data.Count() / 2).ToList();
			fftResult.RemoveRange(0, data.Count() / 2);
			fftResult.AddRange(tempList);
			fftExpand = fftResult;
			for (int i = fftExpand.Count / 2 - 5; i < fftExpand.Count / 2 + 10; i++)
			{
				fftExpand[i].Real = 0.0;
				fftExpand[i].Image = 0.0;
			}
			enhancement = FreqAnalyzer.FFT(fftExpand.ToArray(), invert: false).ToList();
			data = FreqAnalyzer.Cmp2Mdl(enhancement.ToArray());
			break;
		}
		}
		return data.ToList();
	}

	public static List<PeakInfo> findPeak(double[] time, double[] data, FindPeakType findPeakType, double minPeak, double minArea, double threshold, double width)
	{
		double[] derivative = new double[data.Length];
		List<PeakInfo> peakInfos = new List<PeakInfo>();
		if (findPeakType == FindPeakType.Comparison)
		{
			for (int i = 3; i < data.Count() - 3; i++)
			{
				if (!(data[i] > data[i - 1]) || !(data[i] > data[i - 2]) || !(data[i] > data[i - 3]) || !(data[i] > data[i + 1]) || !(data[i] > data[i + 2]) || !(data[i] > data[i + 3]) || !(data[i] > minPeak))
				{
					continue;
				}
				PeakInfo peakinfo = default(PeakInfo);
				peakinfo.positionindex = i;
				peakinfo.position = time[i];
				int k = i;
				while (k > 0)
				{
					if (data[k] > data[k - 1])
					{
						k--;
						continue;
					}
					peakinfo.startindex = k;
					peakinfo.start = time[k];
					break;
				}
				for (int j = i; j < data.Length - 1; j++)
				{
					if (!(data[j] > data[j + 1]))
					{
						peakinfo.endindex = j;
						peakinfo.end = time[j];
						break;
					}
				}
				if (peakinfo.end - peakinfo.start > width && data[peakinfo.positionindex] > minPeak)
				{
					peakInfos.Add(peakinfo);
				}
			}
		}
		return peakInfos;
	}
}
